﻿#region Copyright information
// 
// Copyright © 2005-2013 Yongkee Cho. All rights reserved.
// 
// This code is a part of the Biological Object Library and governed under the terms of the
// GNU Lesser General  Public License (LGPL) version 2.1 which accompanies this distribution.
// For more information on the LGPL, please visit http://bol.codeplex.com/license.
// 
// - Filename: Phenotype.cs
// - Author: Yongkee Cho
// - Email: yongkeecho@gmail.com
// - Date Created: 2013-01-25 3:25 PM
// - Last Modified: 2013-01-25 3:59 PM
// 
#endregion
using System;
using System.Runtime.Serialization;

namespace BOL.Models
{
    [DataContract(Namespace = "")]
    public struct Phenotype<TValue> : ICloneable, INamed, IValued<TValue>, IComparable, IComparable<Phenotype<TValue>>, IEquatable<Phenotype<TValue>>
        where TValue : IComparable
    {
        #region Public properties

        public TValue Value { get; set; }

        /// <summary>Gets or sets the name.</summary>
        public string Name { get; set; }

        #endregion

        #region Constructors

        public Phenotype(string name, TValue value)
            : this()
        {
            Name = name;
            Value = value;
        }

        #endregion

        #region ICloneable implementation

        public Phenotype<TValue> Clone()
        {
            return new Phenotype<TValue>(Name, Value);
        }

        #if !(SILVERLIGHT || WINDOWS_PHONE)
        object ICloneable.Clone()
        {
            return Clone();
        }
        #endif

        #endregion

        #region IComparable, IComparable<Phenotype<TValue>>, IEquatable<Phenotype<TValue>> implementation

        public int CompareTo(object other)
        {
            if (other == null)
                throw new ArgumentNullException("other");

            if (!(other is TValue))
                throw new InvalidCastException("The 'other' argument is not a Phenotype<TValue> object.");

            return CompareTo((Phenotype<TValue>)other);
        }

        public int CompareTo(Phenotype<TValue> other)
        {
            if (!Name.Equals(other.Name))
                throw new ArgumentException("Bad comparison.");

            return Value.CompareTo(other.Value);
        }

        public bool Equals(Phenotype<TValue> other)
        {
            return Name.Equals(other.Name) & Value.Equals(other.Value);
        }

        #endregion

        #region Object overriden

        public override int GetHashCode()
        {
            return Name.GetHashCode() ^ Value.GetHashCode();
        }

        public override bool Equals(object other)
        {
            if (other == null)
                throw new ArgumentNullException("other");

            if (!(other is TValue))
                throw new InvalidCastException("The 'other' argument is not a Phenotype<TValue> object.");
            
            return Equals((Phenotype<TValue>)other);
        }

        public override string ToString()
        {
            return String.Format("{0} = {1}", Name, Value);
        }

        #endregion
    }
}
